package com.zenithmind.note.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.note.mapper.NoteFavoriteMapper;
import com.zenithmind.note.mapper.NoteMapper;
import com.zenithmind.note.pojo.entity.Note;
import com.zenithmind.note.pojo.entity.NoteFavorite;
import com.zenithmind.note.pojo.query.NoteFavoriteQuery;
import com.zenithmind.note.pojo.query.UserFavoriteQuery;
import com.zenithmind.note.pojo.vo.NoteVO;
import com.zenithmind.note.service.NoteFavoriteService;
import com.zenithmind.note.service.NoteService;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.result.Result;
import com.zenithmind.common.exception.UnauthorizedException;
import com.zenithmind.common.annotation.DataCache;
import com.zenithmind.common.annotation.DataCacheEvict;
import com.zenithmind.common.constant.CacheConstants;
import com.zenithmind.common.security.SecurityUtils;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 笔记收藏服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class NoteFavoriteServiceImpl extends ServiceImpl<NoteFavoriteMapper, NoteFavorite> implements NoteFavoriteService {
    
    private final NoteMapper noteMapper;
    private final NoteService noteService;
    
    // 缓存相关常量
    private static final String CACHE_FAVORITE_PREFIX = "note:favorite";
    private static final String CACHE_USER_FAVORITE_PREFIX = "user:favorite";
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Boolean> favoriteNote(String noteId) {
        // 直接在方法内获取用户ID并验证
        String userId = SecurityUtils.getCurrentUserId();
        if (StringUtils.isBlank(userId)) {
            throw new UnauthorizedException("用户未登录");
        }
        
        // 查询笔记是否存在
        Note note = noteMapper.selectById(noteId);
        if (note == null) {
            throw new RuntimeException("笔记不存在");
        }
        
        // 查询是否已收藏
        LambdaQueryWrapper<NoteFavorite> wrapper = Wrappers.<NoteFavorite>lambdaQuery()
                .eq(NoteFavorite::getNoteId, noteId)
                .eq(NoteFavorite::getUserId, userId);
        NoteFavorite favorite = this.getOne(wrapper);
        
        if (favorite != null) {
            // 已收藏，不需要操作
            return Result.success(false);
        }
        
        // 添加收藏
        favorite = new NoteFavorite();
        favorite.setNoteId(noteId);
        favorite.setUserId(userId);
        boolean saved = this.save(favorite);
        return Result.success(saved);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    @DataCacheEvict(prefix = CACHE_USER_FAVORITE_PREFIX, key = "#userId")
    public Result<Boolean> favoriteNote(String noteId, String userId) {
        // 查询笔记是否存在
        Note note = noteMapper.selectById(noteId);
        if (note == null) {
            throw new RuntimeException("笔记不存在");
        }
        
        // 查询是否已收藏
        LambdaQueryWrapper<NoteFavorite> wrapper = Wrappers.<NoteFavorite>lambdaQuery()
                .eq(NoteFavorite::getNoteId, noteId)
                .eq(NoteFavorite::getUserId, userId);
        NoteFavorite favorite = this.getOne(wrapper);
        
        if (favorite != null) {
            // 已收藏，不需要操作
            return Result.success(false);
        }
        
        // 添加收藏
        favorite = new NoteFavorite();
        favorite.setNoteId(noteId);
        favorite.setUserId(userId);
        boolean saved = this.save(favorite);
        return Result.success(saved);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Boolean> unfavoriteNote(String noteId) {
        // 直接在方法内获取用户ID并验证
        String userId = SecurityUtils.getCurrentUserId();
        if (StringUtils.isBlank(userId)) {
            throw new UnauthorizedException("用户未登录");
        }
        
        // 查询是否已收藏
        LambdaQueryWrapper<NoteFavorite> wrapper = Wrappers.<NoteFavorite>lambdaQuery()
                .eq(NoteFavorite::getNoteId, noteId)
                .eq(NoteFavorite::getUserId, userId);
        
        boolean removed = this.remove(wrapper);
        return Result.success(removed);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    @DataCacheEvict(prefix = CACHE_USER_FAVORITE_PREFIX, key = "#userId")
    public Result<Boolean> unfavoriteNote(String noteId, String userId) {
        // 查询是否已收藏
        LambdaQueryWrapper<NoteFavorite> wrapper = Wrappers.<NoteFavorite>lambdaQuery()
                .eq(NoteFavorite::getNoteId, noteId)
                .eq(NoteFavorite::getUserId, userId);
        
        boolean removed = this.remove(wrapper);
        return Result.success(removed);
    }
    
    @Override
    public PageResult<NoteVO> getUserFavorites(long current, long size) {
        // 直接在方法内获取用户ID并验证
        String userId = SecurityUtils.getCurrentUserId();
        if (StringUtils.isBlank(userId)) {
            throw new UnauthorizedException("用户未登录");
        }
        
        // 分页查询用户收藏的笔记ID
        Page<NoteFavorite> page = new Page<>(current, size);
        LambdaQueryWrapper<NoteFavorite> wrapper = Wrappers.<NoteFavorite>lambdaQuery()
                .eq(NoteFavorite::getUserId, userId)
                .orderByDesc(NoteFavorite::getCreateTime);
        
        Page<NoteFavorite> favoritePage = this.page(page, wrapper);
        
        if (favoritePage.getRecords().isEmpty()) {
            return PageResult.of(List.of(), favoritePage.getTotal(), favoritePage.getCurrent(), favoritePage.getSize());
        }
        
        // 获取收藏的笔记ID
        List<String> noteIds = favoritePage.getRecords().stream()
                .map(NoteFavorite::getNoteId)
                .collect(Collectors.toList());
        
        // 查询笔记详情
        LambdaQueryWrapper<Note> noteWrapper = Wrappers.<Note>lambdaQuery()
                .in(Note::getId, noteIds);
        List<Note> notes = noteMapper.selectList(noteWrapper);
        
        // 转换为VO
        List<NoteVO> noteVOs = notes.stream()
                .map(note -> {
                    NoteVO vo = new NoteVO();
                    BeanUtils.copyProperties(note, vo);
                    return vo;
                })
                .collect(Collectors.toList());
        
        return PageResult.of(noteVOs, favoritePage.getTotal(), favoritePage.getCurrent(), favoritePage.getSize());
    }
    
    @Override
    public Result<Boolean> isFavorited(String noteId) {
        // 直接在方法内获取用户ID并验证
        String userId = SecurityUtils.getCurrentUserId();
        if (StringUtils.isBlank(userId)) {
            throw new UnauthorizedException("用户未登录");
        }
        
        if (userId == null) {
            return Result.success(false);
        }
        
        LambdaQueryWrapper<NoteFavorite> wrapper = Wrappers.<NoteFavorite>lambdaQuery()
                .eq(NoteFavorite::getNoteId, noteId)
                .eq(NoteFavorite::getUserId, userId);
        
        long count = this.count(wrapper);
        return Result.success(count > 0);
    }

    /**
     * 后台管理-分页查询收藏记录
     */
    @Override
    public PageResult<NoteFavorite> favoriteManagePage(NoteFavoriteQuery query) {
        // 获取Page对象
        Page<NoteFavorite> page = query.toPage();
        
        // 构建查询条件
        LambdaQueryWrapper<NoteFavorite> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(query.getNoteId() != null && !query.getNoteId().isEmpty(), NoteFavorite::getNoteId, query.getNoteId())
              .eq(query.getUserId() != null, NoteFavorite::getUserId, query.getUserId())
              .orderByDesc(NoteFavorite::getCreateTime);
              
        // 执行分页查询
        Page<NoteFavorite> favoritePage = page(page, wrapper);
        
        // 返回分页结果
        return PageResult.of(
            favoritePage.getRecords(),
            favoritePage.getTotal(),
            favoritePage.getCurrent(),
            favoritePage.getSize()
        );
    }

    /**
     * 后台管理-获取收藏详情
     */
    @Override
    @DataCache(prefix = CACHE_FAVORITE_PREFIX, key = "#favoriteId", expireTime = CacheConstants.TTL_SECONDS_DEFAULT)
    public NoteFavorite getFavoriteById(String favoriteId) {
        NoteFavorite favorite = getById(favoriteId);
        if (favorite == null) {
            throw new RuntimeException("收藏记录不存在");
        }
        return favorite;
    }

    /**
     * 后台管理-添加或修改收藏记录
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @DataCacheEvict(prefix = CACHE_FAVORITE_PREFIX, allEntries = true)
    public NoteFavorite addOrUpdateFavorite(NoteFavorite favorite) {
        // 如果是修改操作
        if (StringUtils.isNotBlank(favorite.getId())) {
            NoteFavorite existingFavorite = getById(favorite.getId());
            if (existingFavorite == null) {
                throw new RuntimeException("收藏记录不存在");
            }
            
            // 更新收藏记录
            updateById(favorite);
        } else {
            // 新增收藏记录
            save(favorite);
        }
        
        // 返回更新后的收藏信息
        return getById(favorite.getId());
    }

    /**
     * 后台管理-批量删除收藏记录
     */
    @Override
    @Transactional
    public void deleteBatch(List<String> ids) {
        if (ids == null || ids.isEmpty()) {
            return;
        }
        
        log.info("批量删除收藏记录：{}", ids);
        
        try {
            // 执行批量删除
            removeByIds(ids);
        } catch (Exception e) {
            log.error("批量删除收藏记录失败：{}", e.getMessage(), e);
            throw new RuntimeException("批量删除收藏记录失败", e);
        }
    }

    /**
     * 查询用户收藏的笔记列表 - 使用查询对象
     */
    @Override
    public PageResult<NoteVO> getUserFavoritePage(UserFavoriteQuery query) {
        // 直接在方法内获取用户ID并验证
        String userId = SecurityUtils.getCurrentUserId();
        if (StringUtils.isBlank(userId)) {
            throw new UnauthorizedException("用户未登录");
        }
        
        // 创建分页对象
        Page<NoteFavorite> page = query.toPage();
        
        // 分页查询用户收藏的笔记ID
        LambdaQueryWrapper<NoteFavorite> wrapper = Wrappers.<NoteFavorite>lambdaQuery()
                .eq(NoteFavorite::getUserId, userId)
                .orderByDesc(NoteFavorite::getCreateTime);
        
        Page<NoteFavorite> favoritePage = this.page(page, wrapper);
        
        if (favoritePage.getRecords().isEmpty()) {
            return PageResult.of(List.of(), favoritePage.getTotal(), favoritePage.getCurrent(), favoritePage.getSize());
        }
        
        // 获取收藏的笔记ID
        List<String> noteIds = favoritePage.getRecords().stream()
                .map(NoteFavorite::getNoteId)
                .collect(Collectors.toList());
        
        // 查询笔记详情，加入标题和标签的筛选条件
        LambdaQueryWrapper<Note> noteWrapper = Wrappers.<Note>lambdaQuery()
                .in(Note::getId, noteIds)
                .like(StringUtils.isNotBlank(query.getTitle()), Note::getTitle, query.getTitle())
                .like(StringUtils.isNotBlank(query.getTag()), Note::getTags, query.getTag());
        
        List<Note> notes = noteMapper.selectList(noteWrapper);
        
        // 转换为VO
        List<NoteVO> noteVOs = notes.stream()
                .map(note -> {
                    NoteVO vo = new NoteVO();
                    BeanUtils.copyProperties(note, vo);
                    return vo;
                })
                .collect(Collectors.toList());
        
        // 重新计算总记录数，考虑标题和标签筛选后的结果
        long filteredTotal = noteVOs.size();
        
        return PageResult.of(noteVOs, filteredTotal, query.getCurrent().longValue(), query.getSize().longValue());
    }

    /**
     * 分页查询用户收藏的笔记列表 - 外部传入用户ID
     */
    @Override
    @DataCache(prefix = CACHE_USER_FAVORITE_PREFIX, key = "#userId", expireTime = CacheConstants.TTL_SECONDS_USER)
    public PageResult<NoteVO> getUserFavorites(String userId, long current, long size) {
        // 分页查询用户收藏的笔记ID
        Page<NoteFavorite> page = new Page<>(current, size);
        LambdaQueryWrapper<NoteFavorite> wrapper = Wrappers.<NoteFavorite>lambdaQuery()
                .eq(NoteFavorite::getUserId, userId)
                .orderByDesc(NoteFavorite::getCreateTime);
        
        Page<NoteFavorite> favoritePage = this.page(page, wrapper);
        
        if (favoritePage.getRecords().isEmpty()) {
            return PageResult.of(List.of(), favoritePage.getTotal(), favoritePage.getCurrent(), favoritePage.getSize());
        }
        
        // 获取收藏的笔记ID
        List<String> noteIds = favoritePage.getRecords().stream()
                .map(NoteFavorite::getNoteId)
                .collect(Collectors.toList());
        
        // 查询笔记详情
        LambdaQueryWrapper<Note> noteWrapper = Wrappers.<Note>lambdaQuery()
                .in(Note::getId, noteIds);
        List<Note> notes = noteMapper.selectList(noteWrapper);
        
        // 转换为VO
        List<NoteVO> noteVOs = notes.stream()
                .map(note -> {
                    NoteVO vo = new NoteVO();
                    BeanUtils.copyProperties(note, vo);
                    return vo;
                })
                .collect(Collectors.toList());
        
        return PageResult.of(noteVOs, favoritePage.getTotal(), favoritePage.getCurrent(), favoritePage.getSize());
    }

    /**
     * 判断用户是否收藏了笔记 - 外部传入用户ID
     */
    @Override
    @DataCache(prefix = CACHE_FAVORITE_PREFIX, key = "#noteId + ':' + #userId", expireTime = CacheConstants.TTL_SECONDS_USER)
    public Result<Boolean> isFavorited(String noteId, String userId) {
        if (userId == null) {
            return Result.success(false);
        }
        
        LambdaQueryWrapper<NoteFavorite> wrapper = Wrappers.<NoteFavorite>lambdaQuery()
                .eq(NoteFavorite::getNoteId, noteId)
                .eq(NoteFavorite::getUserId, userId);
        
        long count = this.count(wrapper);
        return Result.success(count > 0);
    }
} 